package com.funtl.framework.java.util.mail;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

import com.funtl.framework.java.util.file.FileRead;

/**
 * HTML格式的邮件
 * @author lusifer
 *
 */
public class SMTPHtmlSender {
	private String send;				//发送邮件服务器信息
	private String fm;					//发件人
	private String username;			//用户名
	private String password;			//密码
	
	/**
	 * SMTP协议邮件，HTML，参数可以使用MailParam中定义的常量
	 * @param send		邮件服务 - smtp.qq.com
	 * @param fm		发件人     - lwm@huahongtop.com
	 * @param username	用户名
	 * @param password	密码
	 */
	public SMTPHtmlSender(String send, String fm, String username, String password) {
		this.send = send;
		this.fm = fm;
		this.username = username;
		this.password = password;
	}
	
	/**
	 * 多人邮件（不会暴露出全部收件人地址）
	 * @param too 收件人
	 * @param subject 主题
	 * @param body 内容
	 * @param print 是否打印测试信息
	 * @return 0 - 发送成功，1 - 无效的地址，2 - 无效的协议，3 - 消息设置异常
	 */
	public int sendEmail(String[] to, String subject, String body, boolean print) {
		try {
			Session session = createSession(print);
			for (int i = 0 ; i < to.length ; i++)  {
				MimeMessage message = createMessage(session, to[i], subject, body);

				// 获得Transport对象，并连接邮件服务器发送邮件
				Transport transport = session.getTransport();
				transport.connect(send, username, password);
				transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
				transport.close();
			}
		} catch (AddressException e) {
			e.printStackTrace();
			return 1;
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			return 2;
		} catch (MessagingException e) {
			e.printStackTrace();
			return 3;
		}
		
		return 0;
	}
	
	/**
	 * 多人邮件（会暴露出全部收件人地址）
	 * @param too 收件人
	 * @param subject 主题
	 * @param body 内容
	 * @param print 是否打印测试信息
	 * @return 0 - 发送成功，1 - 无效的地址，2 - 无效的协议，3 - 消息设置异常
	 */
	public int sendMultiEmail(String[] too, String subject, String body, boolean print) {
		try {
			Session session = createSession(print);
			MimeMessage message = createMultiMessage(session, too, subject, body);
			// 获得Transport对象，并连接邮件服务器发送邮件
			Transport transport = session.getTransport();
			transport.connect(send, username, password);
			transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
			transport.close();
		} catch (AddressException e) {
			e.printStackTrace();
			return 1;
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			return 2;
		} catch (MessagingException e) {
			e.printStackTrace();
			return 3;
		}
		
		return 0;
	}
	
	/**
	 * 群发邮件（不会暴露全部收件人地址），通常会被当做垃圾邮件或因为管制等原因发送失败，即使发送成功也有可能内容加载失败
	 * @param sendSMTPAddress SMTP地址，随便填写，一般填写自家邮件域名即可，mail.w951.com
	 * @param from 发件人
	 * @param subject 主题
	 * @param body 内容
	 * @param to 收件人，数组
	 * @param print 是否打印测试信息
	 * @return 0 - 发送成功，1 - 无效的地址，2 - 消息设置异常，3 - DNS解析错误
	 */
	public int sendMassEmail(String sendSMTPAddress, String from, String subject, String body, String[] to, boolean print) {
		Properties props = new Properties();
		props.setProperty(MailParam.SMTP_LOCALHOST, sendSMTPAddress);
		Session session = Session.getInstance(props);
		session.setDebug(print);
		try {
			Message msg = createMessage(session, from, subject, body);
			for (int i = 0; i < to.length; i++) {
				sendMessage(session, msg, to[i]);
			}
		} catch (AddressException e) {
			e.printStackTrace();
			return 1;
		} catch (MessagingException e) {
			e.printStackTrace();
			return 2;
		} catch (NamingException e) {
			e.printStackTrace();
			return 3;
		}
		
		return 0;
	}
	
	private MimeMessage createMessage(Session session, String to, String subject, String body) throws AddressException, MessagingException {
		MimeMessage message = new MimeMessage(session);
		message.setFrom(new InternetAddress(fm));
		message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
		message.setSubject(subject);
		MimeMultipart multipart = new MimeMultipart("related");
		MimeBodyPart htmlBodyPart = new MimeBodyPart();
		htmlBodyPart.setContent(body, "text/html;charset=gb2312");
		multipart.addBodyPart(htmlBodyPart);
		
		//下面这段代码可以在邮件内放入图片并指定一个ID，发送邮件时可以直接在<img src="cid:imageId" />嵌入图片
//		MimeBodyPart gifBodyPart = new MimeBodyPart();
//		FileDataSource fds = new FileDataSource("d:/Images/google_logo_116x41.png");
//		gifBodyPart.setDataHandler(new DataHandler(fds));
//		gifBodyPart.setContentID("google_logo_116x41.png"); //设置图片ID
//		multipart.addBodyPart(gifBodyPart);

		message.setContent(multipart);
		message.saveChanges();
		return message;
	}
	
	private MimeMessage createMultiMessage(Session session, String[] too, String subject, String body) throws AddressException, MessagingException {
		MimeMessage message = new MimeMessage(session);
		message.setFrom(new InternetAddress(fm));
		for (int i = 0 ; i < too.length ; i++) {
			message.addRecipients(Message.RecipientType.TO, InternetAddress.parse(too[i]));
		}
		message.setSubject(subject);
		MimeMultipart multipart = new MimeMultipart("related");
		MimeBodyPart htmlBodyPart = new MimeBodyPart();
		htmlBodyPart.setContent(body, "text/html;charset=gb2312");
		multipart.addBodyPart(htmlBodyPart);
		
		//下面这段代码可以在邮件内放入图片并指定一个ID，发送邮件时可以直接在<img src="cid:imageId" />嵌入图片
//		MimeBodyPart gifBodyPart = new MimeBodyPart();
//		FileDataSource fds = new FileDataSource("d:/Images/google_logo_116x41.png");
//		gifBodyPart.setDataHandler(new DataHandler(fds));
//		gifBodyPart.setContentID("google_logo_116x41.png"); //设置图片ID
//		multipart.addBodyPart(gifBodyPart);

		message.setContent(multipart);
		message.saveChanges();
		return message;
	}
	
	private Session createSession(boolean print){
		Properties props = new Properties();
		props.setProperty(MailParam.TRANSPORT, MailParam.SMTP_PROTOCOL);
		props.setProperty(MailParam.SMTP_AUTH, "true");
		Session session = Session.getInstance(props);
		session.setDebug(print);
		return session;
	}
	
	private void sendMessage(Session session, Message msg, String to) throws AddressException, NoSuchProviderException, MessagingException, NamingException {
		// 设置邮件内容的收件人并生成邮件消息内容
		msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
		msg.saveChanges();

		// 连接收件人地址所在的SMTP服务器并发送邮件
		Transport transport = session.getTransport(MailParam.SMTP_PROTOCOL);
		String domain = to.substring(to.indexOf("@") + 1);
		String smtpServer = getSmtpServer(domain, null);
		transport.connect(smtpServer, null, null);
		transport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));
		transport.close();
	}
	
	private String getSmtpServer(String domain, String dnsServer) throws NamingException {
		DirContext ctx = new InitialDirContext();
		Attributes attrsMx = null;
		if (dnsServer != null) {
			attrsMx = ctx.getAttributes("dns:" + "//" + dnsServer + "/" + domain, new String[] { "MX" });
		} else {
			attrsMx = ctx.getAttributes("dns:" + "/" + domain, new String[] { "MX" });
		}
		String recordMx = (String) attrsMx.get("MX").get();
		String smtpServer = recordMx.substring(recordMx.indexOf(" ") + 1);
		return smtpServer;
	}
	
	public static void main(String[] args) throws Exception {
		SMTPHtmlSender htmlSender = new SMTPHtmlSender(MailParam.SEND_SMTP_QQ_EX, "lwm@huahongtop.com", "lwm@huahongtop.com", "lwm1303311");
		String[] to = new String[] {"topsale@vip.qq.com", "lwm@huahongtop.com", "topsale86@gmail.com"};
		
		htmlSender.sendEmail(to, "这是一封批量逐个发送HTML格式的测试邮件，不会暴露全部收件人地址", FileRead.readHtml("d:/html/test.html"), true);
		
//		htmlSender.sendMultiEmail(to, "这是一封多人发送HTML格式的测试邮件，会暴露全部收件人地址", FileRead.readHtml("d:/html/test.html"), true);
//		
//		htmlSender.sendMassEmail("mail.itcast.cn", "lwm@huahongtop.com", "这是一封群发测试HTML格式的邮件，不会暴露全部收件人地址", FileRead.readHtml("d:/html/test.html"), to, true);
	}
	
}
